package org.vacoor.nothing.web.domain.filter;

import org.vacoor.nothing.common.util.Castor;

/**
 */
public class Rule {
    public enum Op {
        /* number & string op */
        EQ("="),
        NE("<>"), // <> / !=
        LT("<"),
        LE("<="),
        GT(">"),
        GE(">="),
        NU("IS NULL"),
        NN("IS NOT NULL"),
        // IN, // 属于 ?
        // NI, // 不属于 ?
        /* string op */
        BW("LIKE") {    // begins with

            @Override
            public Object wrap(Object value) {
                String str = Castor.asString(value);
                return null != str && !str.endsWith("%") ? str + '%' : str;
            }

        },
        BN("NOT LIKE") {// not begins with

            @Override
            public Object wrap(Object value) {
                String str = Castor.asString(value);
                return null != str && !str.endsWith("%") ? str + '%' : str;
            }
        },
        EW("LIKE") { // ends with

            @Override
            public Object wrap(Object value) {
                String str = Castor.asString(value);
                return null != str && !str.startsWith("%") ? '%' + str : str;
            }
        },
        EN("NOT LIKE") { // not ends with

            @Override
            public Object wrap(Object value) {
                String str = Castor.asString(value);
                return null != str && !str.startsWith("%") ? '%' + str : str;
            }
        },
        CN("LIKE") { // contains

            @Override
            public Object wrap(Object value) {
                return EW.wrap(BW.wrap(value));
            }
        },
        NC("NOT LIKE") { // not contains

            @Override
            public Object wrap(Object value) {
                return EW.wrap(BW.wrap(value));
            }
        };

        public static Op forName(String name) {
            try {
                return valueOf(name.toUpperCase());
            } catch (Exception e) {
                return null;
            }
        }

        final String op;

        private Op(String op) {
            this.op = op;
        }

        public Object wrap(Object value) {
            return value;
        }

        @Override
        public String toString() {
            return op;
        }
    }

    /* ************************
     *
     * ********************** */

    private final String property;
    private final Op op;
    private final Object value;

    public Rule(String property, Op op, Object value) {
        this.property = property;
        this.op = op;
        this.value = value;
    }

    public String getProperty() {
        return property;
    }

    public Op getOp() {
        return op;
    }

    public Object getValue() {
        return value;
    }

    public static Rule create(String property, Op op, Object value) {
        if (null == property || null == op) {
            throw new IllegalArgumentException();
        }
        return new Rule(property, op, value);
    }

    public static Rule eq(String property, Object value) {
        return create(property, Op.EQ, value);
    }

    public static Rule ne(String property, Object value) {
        return create(property, Op.NE, value);
    }

    public static Rule lt(String property, Object value) {
        return create(property, Op.LT, value);
    }

    public static Rule le(String property, Object value) {
        return create(property, Op.LE, value);
    }

    public static Rule gt(String property, Object value) {
        return create(property, Op.GT, value);
    }

    public static Rule ge(String property, Object value) {
        return create(property, Op.GE, value);
    }

    public static Rule isNull(String property) {
        return create(property, Op.NU, null);
    }
}
